package org.lmind.example.util.text;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegExpTextSearcher {

	private Pattern pattern;
	
	private int groupIndex;
	
	public RegExpTextSearcher(Pattern pattern, int groupIndex) {
		super();
		this.pattern = pattern;
		this.groupIndex = groupIndex;
	}

	public TextMatch search(String text) {
		Matcher m = pattern.matcher(text);
		TextMatchImpl impl = new TextMatchImpl();
		impl.text = text;
		impl.matcher = m;
		return impl;
	}
	
	class Replacement {
		private String text;
		private String newText;
		private int start;
		private int end;
	}
	
	class TextMatchImpl implements TextMatch {
		
		private String text;
		
		private Matcher matcher;
		
		private ArrayList<Replacement> replacements = new ArrayList<Replacement>();
		
		private Replacement replacement;

		@Override
		public boolean next() {

			boolean finded = matcher.find();

			if (replacement != null && replacement.newText != null) {
				replacements.add(replacement);
			}
			replacement = null;

			if (finded) {
				replacement = new Replacement();
				replacement.text = matcher.group(groupIndex);
				replacement.start = matcher.start(groupIndex);
				replacement.end = matcher.end(groupIndex);
			}

			return finded;
		}

		@Override
		public int start() {
			return replacement.start;
		}

		@Override
		public int end() {
			return replacement.end;
		}

		@Override
		public String text() {
			return replacement.text;
		}

		@Override
		public void replace(String newText) {
			replacement.newText = newText;
		}

		@Override
		public String apply() {
			StringBuilder sb = new StringBuilder();
			
			int offset = 0;
			for (Replacement item : replacements) {
				sb.append(text.substring(offset, item.start));
				sb.append(item.newText);
				offset = item.end;
			}
			sb.append(text.substring(offset));
			return sb.toString();
		}
		
	}

}
